package com.orderplus.opshop.synces.service.product.impl;

import cn.hutool.core.util.EnumUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.orderplus.opshop.common.util.MapUtil;
import com.orderplus.opshop.common.util.StringUtil;
import com.orderplus.opshop.common.util.ValueUtil;
import com.orderplus.opshop.core.data.request.RequestParam;
import com.orderplus.opshop.core.data.response.ResponseData;
import com.orderplus.opshop.core.exception.CheckedException;
import com.orderplus.opshop.synces.bean.ProductDetailModel;
import com.orderplus.opshop.synces.constant.EsConstant;
import com.orderplus.opshop.synces.core.TableNameEnum;
import com.orderplus.opshop.synces.entity.product.Product;
import com.orderplus.opshop.synces.entity.product.ProductAttribute;
import com.orderplus.opshop.synces.mapper.product.IProductMapper;
import com.orderplus.opshop.synces.request.OpEsIndexRequest;
import com.orderplus.opshop.synces.service.elasticsearch.impl.OpDeleteService;
import com.orderplus.opshop.synces.service.elasticsearch.impl.OpIndexService;
import com.orderplus.opshop.synces.service.elasticsearch.impl.OpUpdateService;
import com.orderplus.opshop.synces.service.product.ProductAttributeService;
import com.orderplus.opshop.synces.service.product.ProductPropertyListService;
import com.orderplus.opshop.synces.service.product.ProductPropertyService;
import com.orderplus.opshop.synces.service.product.ProductService;
import com.orderplus.opshop.synces.service.product.ProductSkuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;


@Service
@Slf4j
public class ProductServiceImpl extends ServiceImpl<IProductMapper, Product> implements ProductService {
	@Autowired
	private OpIndexService opIndexService;
	@Autowired
	private OpUpdateService opUpdateService;
	@Autowired
	private OpDeleteService opDeleteService;

	@Autowired
	private ProductPropertyService productPropertyService;
	@Autowired
	private ProductPropertyListService productPropertyListService;
	@Autowired
	private ProductSkuService productSkuService;
	@Autowired
	private ProductAttributeService productAttributeService;

	private String indexType = "list";

	private RequestParam<OpEsIndexRequest> set(String fromTabe, String targetTable, String primaryKey, List<Map<String, Object>> list, String action) {
		RequestParam<OpEsIndexRequest> request = new RequestParam<>();

		OpEsIndexRequest opEsIndexRequest = new OpEsIndexRequest();

		opEsIndexRequest.setPrimaryKeyName(primaryKey);
		opEsIndexRequest.setTableName(targetTable);
//		opEsIndexRequest.setColumns(list);

		TableNameEnum tableNameEnum = EnumUtil.fromString(TableNameEnum.class, fromTabe.toUpperCase());

		List<ProductDetailModel> productlList = null;
		try {
			productlList = convertMapToProductDetailModel(tableNameEnum, list, action);
		} catch (Exception e) {
			e.printStackTrace();
		}
		opEsIndexRequest.setData(productlList);
		opEsIndexRequest.setEsType(indexType);

		request.setRequestBody(opEsIndexRequest);

		return request;
	}

	private List<ProductDetailModel> convertMapToProductDetailModel(TableNameEnum tableNameEnum, List<Map<String, Object>> list, String action) throws Exception {
		List<ProductDetailModel> result = new LinkedList<>();

		if (ValueUtil.isNotEmpty(list)) {
			for (Map<String, Object> map : list) {
				if (ValueUtil.isEmpty(map)) {
					log.error("class productServiceImpl,方法 convertMapToProductDetailModel,参数 map 为空,跳过操作");
					continue;
				}

				switch (tableNameEnum) {
					case PRODUCT:
						ProductDetailModel productDetailModel = null;
						if ("delete".equals(action)) {
							productDetailModel = deleteProductToEs(map);
						} else {
							productDetailModel = mapFromProductToProductDetailModel(map, action);
						}
						result.add(productDetailModel);

						break;
					case PRODUCT_SKU:
						result = productSkuService.mapFromProductSkuToProductDetailModel(map, action, result);

						break;
					case PRODUCT_PROPERTY:
						if ("delete".equals(action)) {

						} else {
							result = productPropertyService.mapFromProductPropertyToProductDetailModel(map, action, result);
						}

						break;
					case PRODUCT_PROPERTY_LIST:
						if ("delete".equals(action)) {
							result = productPropertyListService.queryProductPropertyListToProductDetailModel(map, action, result);
						} else {
							result = productPropertyListService.mapFromProductPropertyListToProductDetailModel(map, action, result);
						}

						break;
					case PRODUCT_ATTRIBUTE:

						break;
					case PRODUCT_ATTRIBUTE_LIST:

						break;
					case PRODUCT_COLOR_IMG:

						break;
					default:
						break;
				}
			}
		}

		return result;
	}

	@Override
	public ResponseData<Boolean> batchAddProductToEs(String tableName, String primaryKey, List<Map<String, Object>> list) {
		RequestParam<OpEsIndexRequest> request = set(tableName, EsConstant.ES_INDICES, primaryKey, list, "add");

		ResponseData<Boolean> result = opIndexService.callInner(request);

		return result;
	}

	@Override
	public ResponseData<Boolean> addProductToEs(String tableName, String primaryKey, Map<String, Object> map) {
		List<Map<String, Object>> list = new LinkedList();

		list.add(map);

		RequestParam<OpEsIndexRequest> request = set(tableName, EsConstant.ES_INDICES, primaryKey, list, "add");

		ResponseData<Boolean> result = opIndexService.callInner(request);

		return result;
	}

	@Override
	public ResponseData<Boolean> updateProductToEs(String tableName, String primaryKey, Map<String, Object> map) {
		LinkedList<Map<String, Object>> list = new LinkedList();

		list.add(map);

		RequestParam<OpEsIndexRequest> request = set(tableName, EsConstant.ES_INDICES, primaryKey, list, "update");

		ResponseData<Boolean> result = opUpdateService.callInner(request);

		return result;
	}

	@Override
	public ResponseData<Boolean> deleteProductToEs(String tableName, Map<String, Object> map) {
		LinkedList<Map<String, Object>> list = new LinkedList();

		list.add(map);

		RequestParam<OpEsIndexRequest> request = set(tableName, EsConstant.ES_INDICES, null, list, "delete");

		ResponseData<Boolean> result = opDeleteService.callInner(request);

		return result;
	}


	@Override
	public ResponseData<Boolean> syncToEsByProduct(String fromTabe, String targetTable, String primaryKey, int size) {
		int count = 0;
		TableNameEnum tableNameEnum = EnumUtil.fromString(TableNameEnum.class, fromTabe.toUpperCase());
		switch (tableNameEnum) {
			case PRODUCT:
				count = baseMapper.selectCount(Wrappers.emptyWrapper());
				break;
			case PRODUCT_PROPERTY:
				count = productPropertyService.count();
				break;
			case PRODUCT_PROPERTY_LIST:
				count = productPropertyListService.count();
				break;
			case PRODUCT_SKU:
				count = productSkuService.count();
				break;
			default:
				break;
		}

		if (size <= 0) {
			size = 5000;
		}

//		分页查询,按照参数每次同步多少条数据.
		int pages = 0;
		if (count % size == 0) {
			pages = count / size;
		} else {
			pages = count / size + 1;
		}

		String action = "update";
		for (int i = 0; i <= pages; i++) {
			Page<Map<String, Object>> page = new Page<>(i, size);
			IPage pageList = null;
			switch (tableNameEnum) {
				case PRODUCT:
					action = "add";
					pageList = baseMapper.pageMap(page);
					break;
				case PRODUCT_PROPERTY:
					pageList = productPropertyService.pageMap(page);
					break;
				case PRODUCT_PROPERTY_LIST:
					pageList = productPropertyListService.pageMap(page);
					break;
				case PRODUCT_SKU:
					pageList = productSkuService.pageMap(page);
					break;
				default:
					break;
			}
			if (null == pageList) {
				throw new CheckedException("找不到" + targetTable + "表格信息");
			}

			RequestParam<OpEsIndexRequest> request = set(fromTabe, targetTable, primaryKey, pageList.getRecords(), action);

			switch (tableNameEnum) {
				case PRODUCT:
					opIndexService.callInner(request);
					break;
				default:
					opUpdateService.callInner(request);
					break;
			}
		}

		ResponseData<Boolean> responseData = new ResponseData<>();
		responseData = ResponseData.success();
		responseData.setData(true);

		return responseData;
	}

	private ProductDetailModel setData(ProductDetailModel productDetailModel, Product product, String action) {
//		把BaseCategoryId和BaseCategoryName set到Category的属性
		if (ValueUtil.isNotEmpty(product.getBaseCategoryId()) || ValueUtil.isNotEmpty(product.getBaseCategoryName())) {
			ProductDetailModel.Category baseCategory = new ProductDetailModel.Category();
			if (ValueUtil.isNotEmpty(product.getBaseCategoryId())) {
				baseCategory.setCategoryId(ValueUtil.toStr(product.getBaseCategoryId()));
			}
			if (ValueUtil.isNotEmpty(product.getBaseCategoryName())) {
				baseCategory.setCategoryName(ValueUtil.toStr(product.getBaseCategoryName()));
			}
			productDetailModel.setBaseCategory(baseCategory);
		}

//		把CategoryCollectId和CategoryCollectName set到Category的属性
		if (ValueUtil.isNotEmpty(product.getCategoryCollectId()) || ValueUtil.isNotEmpty(product.getCategoryCollectName())) {
			ProductDetailModel.Category collectCategory = new ProductDetailModel.Category();
			if (ValueUtil.isNotEmpty(product.getCategoryCollectId())) {
				collectCategory.setCategoryId(ValueUtil.toStr(product.getCategoryCollectId()));
			}
			if (ValueUtil.isNotEmpty(product.getCategoryCollectName())) {
				collectCategory.setCategoryName(ValueUtil.toStr(product.getCategoryCollectName()));
			}
			productDetailModel.setCollectCategory(collectCategory);
		}

//		if ("update".equals(action)) {
		if (ValueUtil.isNotEmpty(product.getImages())) {
			String[] images = StringUtil.toStrArray(product.getImages());

			productDetailModel.setImages(images);
		}
//		} else {
//			productDetailModel.setImages(null);
//			productDetailModel.setMainImage(null);
//			productDetailModel.setFromUrl(null);
//		}

		return productDetailModel;
	}

	//	商品资料表的数据字段转换
	public ProductDetailModel mapFromProductToProductDetailModel(Map<String, Object> map, String action) {
		ProductDetailModel productDetailModel = new ProductDetailModel();

		try {
//			把表名的字段名中包含_替换
			Map<String, Object> newMap = MapUtil.assemble(map);

//			转成product表的数据
			Product product = (Product) MapUtil.mapToObject(newMap, Product.class);

//			从product对象复制到es的结构方式
			BeanUtils.copyProperties(product, productDetailModel);

//			设置主键ID
			productDetailModel.setProductId(ValueUtil.toStr(product.getId()));

			productDetailModel = setData(productDetailModel, product, action);

//			根据商品属性id,放置对应的商品信息
//			List<ProductDetailModel.ProductProperty> productPropSrcMap = productPropertyService.appendPropListToMapObject(product.getPropertyListSrc(), action);
//			if (null != productPropSrcMap) {
//				productDetailModel.setPropertyListSrc(productPropSrcMap);
//			}
			List<ProductDetailModel.ProductProperty> productPropIdsMap = productPropertyService.appendPropListToMapObject(product.getPropertyListIds(), action);
			if (null != productPropIdsMap) {
				productDetailModel.setPropertyListIds(productPropIdsMap);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return productDetailModel;
	}

	public ProductDetailModel deleteProductToEs(Map<String, Object> map) {
		ProductDetailModel productDetailModel = new ProductDetailModel();

		String primaryId = ValueUtil.toStr(map.get("id"));
		productDetailModel.setProductId(primaryId);

		return productDetailModel;
	}

	public ProductDetailModel mapFromProductAttributeToProductDetailModel(Map<String, Object> map) {
		ProductDetailModel productDetailModel = new ProductDetailModel();
		try {
//			把表名的字段名中包含_替换
			Map<String, Object> newMap = MapUtil.assemble(map);

//			转成product表的数据
			ProductAttribute productAttribute = (ProductAttribute) MapUtil.mapToObject(newMap, ProductAttribute.class);

			ProductDetailModel.Attribute attribute = new ProductDetailModel.Attribute();

			if (ValueUtil.isNotEmpty(productAttribute.getId())) {
				attribute.setAttributeId(ValueUtil.toStr(productAttribute.getId()));
			}
			if (ValueUtil.isNotEmpty(productAttribute.getName())) {
				attribute.setAttributeName(productAttribute.getName());
			}
			if (ValueUtil.isNotEmpty(productAttribute.getNameZh())) {
				attribute.setAttributeNameZh(productAttribute.getNameZh());
			}
			if (ValueUtil.isNotEmpty(productAttribute.getNameTh())) {
				attribute.setAttributeNameTh(productAttribute.getNameTh());
			}
			if (ValueUtil.isNotEmpty(productAttribute.getNameId())) {
				attribute.setAttributeNameId(productAttribute.getNameId());
			}

			if (ValueUtil.isNotEmpty(productAttribute.getUpdateTime())) {
				attribute.setAttributeNameId(productAttribute.getNameId());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return productDetailModel;
	}

}